package com.hp.bon.sgw.wh.channel.groupConsistency;

import java.io.IOException;
import java.util.Map;

import org.simpleframework.http.Query;
import org.simpleframework.http.Request;
import org.simpleframework.http.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.internal.util.StringUtils;
import com.hp.bon.sgw.wh.channel.auth.ServAuthService;
import com.hp.bon.sgw.wh.channel.common.BizConsts;
import com.hp.bon.sgw.wh.channel.common.BizParam;
import com.hp.bon.sgw.wh.channel.common.BizResult;
import com.hp.bon.sgw.wh.channel.invoices.BizSlot;
import com.hp.bon.sgw.wh.service.UserResourceConfigService;
import com.hp.bon.sgw.wh.utils.LogUtil;

public class ConsistencyBizProcedure {

    private static final Logger _log = LoggerFactory.getLogger(ConsistencyBizProcedure.class);

    private ConsistencyRequestParser requestParser;
    private ConsistencyBizRouter consistencyBizRouter;
    private ConsistencyResponsor consistencyResponsor;
    private ConsistencyConfigLoader consistencyConfigLoader;
    private ServAuthService servAuthService;

    // private UserResourceConfigService urcService;
    private static ConsistencyBizProcedure consistencyBizProcedure;

    public static ConsistencyBizProcedure instance() {
        if (null == consistencyBizProcedure) {
            consistencyBizProcedure = new ConsistencyBizProcedure();
            consistencyBizProcedure.init();
        }
        return consistencyBizProcedure;
    }

    private void init() {
        //
        requestParser = new ConsistencyRequestParser();
        // 初始化发票接口路由业务类
        consistencyConfigLoader = new ConsistencyConfigLoader();
        //
        consistencyResponsor = new ConsistencyResponsor();
        //
        consistencyBizRouter = new ConsistencyBizRouter();
        consistencyBizRouter.init();
        // 初始化鉴权接口
        servAuthService = ServAuthService.instance();
    }

    public String doProcedure(Request request, Response response, long startTime) {

        // 步骤1： 判断zw_falg 0走老流程,1走新流程
        int zw_flag = UserResourceConfigService.getIntValue("zw_flag", 0);
        if (zw_flag == 0) {
            // 走现在的流程和调用 (老流程)
            return BizConsts.TYPE_ORIG_FLOW;
        }
        // 步骤2：解析请求参数中的latnId
        BizParam bizParam = requestParser.doParser(request);
        // 把Request开始处理的时间加入BizParam中
        bizParam.setParam(BizConsts.KEY_RQUEST_START_TIME, Long.valueOf(startTime));
        String requestPath = bizParam.getParamString(BizConsts.KEY_REQUEST_PATH);
        String requestMethod = bizParam.getParamString(BizConsts.KEY_REQUEST_METHOD);
        // 步骤： 调用鉴权接口
        String objValue = "";
        String objAttr = "2";
        if (BizConsts.RQUEST_METHOD_GET.equals(requestMethod)) {
            try {
                Query query = request.getQuery();
                String accNum = request.getParameter(BizConsts.RQUEST_KEY_ACCNBR) == null ?
                        query.get(BizConsts.RQUEST_KEY_ACCNBR) : request.getParameter(BizConsts.RQUEST_KEY_ACCNBR);
                objValue = accNum;
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            String parsedBody = bizParam.getParamString(BizConsts.KEY_REQUEST_BODY);
            JSONObject bodyObject = JSON.parseObject(parsedBody);
            JSONObject svcObj = bodyObject.getJSONObject("svcObjectStruct");

            if (BizConsts.VALUE_PATH_QRY_BILL.equals(requestPath)) {
                objValue = bodyObject.getString("destinationAccount");
                objAttr = bodyObject.getString("destinationAttr");
            } else if (BizConsts.VALUE_PATH_QRY_CUST_BILL.equals(requestPath)) {
                objValue = bodyObject.getString("accNbr");
                objAttr = bodyObject.getString("destinationAttr");
            } else {
                objValue = svcObj.getString("objValue");
                objAttr = svcObj.getString("objAttr");
            }
        }


        BizParam authParam = new BizParam();
        authParam.setParam(BizConsts.KEY_ACC_NUM, objValue);
        authParam.setParam(BizConsts.KEY_OBJ_ATTR, objAttr);
        BizResult authResult = servAuthService.doAuthService(authParam);
        if (BizConsts.STATUS_ACOUNT_API_SUCCESS.equals(authResult.getCode())) {
            // 把认证成功以结果信息，填入bizParam
            String authBody = authResult.getHttpBody();
            @SuppressWarnings("unchecked")
            Map<String, Object> josnAuth = JSON.parseObject(authBody, Map.class);
            bizParam.setParam("acctId", String.valueOf(josnAuth.get("acctId")));
            bizParam.setParam("prodInstId", String.valueOf(josnAuth.get("prodInstId")));
            bizParam.setParam("areaCode", String.valueOf(josnAuth.get("areaCode")));
            bizParam.setParam(BizConsts.KEY_LANID, String.valueOf(josnAuth.get("regionId")));
            bizParam.setParam("paymentFlag", String.valueOf(josnAuth.get("paymentFlag")));
            //bizParam.setParam("statusCd", String.valueOf(josnAuth.get("statusCd")));
        } else {
            // 认证失败
            consistencyResponsor.doExceptionResponse(response, "9999", "ServAuth fail");
            return BizConsts.TYPE_ERROR_FLOW;
        }

        // 步骤3：据参数及规则，判断是否要执行新流程
        // 3.1 API URL 或 能力名判断
        if (!ConsistencyApiUrls.hasApiUris(bizParam.getParamString(BizConsts.KEY_REQUEST_PATH))) {
            _log.info("the urls of new flow: {}", ConsistencyApiUrls.listApiUrls());
            // 走现在的流程和调用 (老流程)
            return BizConsts.TYPE_ORIG_FLOW;
        }

        // 3.2 lanId判断
        String latnId = bizParam.getParamString(BizConsts.KEY_LANID);
        if (!StringUtils.isEmpty(latnId)) {
            String zwLatn = UserResourceConfigService.getValue("zw_latn", "");
            _log.info("zwLatn={}", zwLatn);
            if (!(zwLatn.equals("888") || zwLatn.indexOf(latnId) >= 0)) {
                return BizConsts.TYPE_ORIG_FLOW;
            }
        } else {
            _log.error("config: latnId={}, ", JSON.toJSONString(bizParam));
            consistencyResponsor.doExceptionResponse(response, "9999", "zw latn config fail");
            return BizConsts.TYPE_ERROR_FLOW;
        }

        if (requestPath.equals("QryCustBill")) {
            String billingCycle = "";
            String billEnv = UserResourceConfigService.getValue("BillDetailQuery");
            try {
                billingCycle = request.getQuery().get("billingCycle");
                _log.info("billingCycle : {}" , billingCycle);
            } catch (Exception e) {
                _log.error(e.toString());
            }
            int pain = 0;
            String[] billEnvs = billEnv.split(",");
            for (String item : billEnvs) {
                String[] items = item.split("\\|");
                String itemName = items[0];
                String itemYmd = items[1];
                if (latnId.equals(itemName) && Integer.valueOf(billingCycle) >= Integer.valueOf(itemYmd)) {
                    pain++;
                    break;
                }
            }
            if (pain == 0) return BizConsts.TYPE_ORIG_FLOW;

        }


        // 步骤4：把配置信息加入BizParam中
        bizParam = consistencyConfigLoader.doLoader(bizParam);
        // Check PARAM && doResponse
        if (!consistencyResponsor.checkParamAndDoResponse(response, bizParam)) {
            // 请求参数存在异常
            return BizConsts.TYPE_ERROR_FLOW;
        }

        // 步骤5：路由到请求对应的处理类：slot
        //  String requestPath = bizParam.getParamString(BizConsts.KEY_REQUEST_PATH);


        BizSlot bizSlot = consistencyBizRouter.routeBizSlot(requestPath, requestMethod);
        if (null == bizSlot) {
            // 直接Response错误信息
            consistencyResponsor.doExceptionResponse(response, "9999", "biz service config fail");
            return BizConsts.TYPE_ERROR_FLOW;
        }

        // 步骤6：路由到请求对应的处理类：slot,做业务处理(调用新帐务中心接口)
        // doBiz不允许向外抛异常
        BizResult bizResult = new BizResult();
        try {
            bizResult = bizSlot.doBiz(bizParam);
        } catch (Exception e) {
            bizResult.setCode(BizConsts.STATUS_ACOUNT_API_FAIL);
            _log.error(e.toString());
        }
        _log.info("bizResult ======{}", JSONObject.toJSONString(bizResult));
        if (bizResult.getCode() != null && bizResult.getCode().equals(BizConsts.STATUS_ACOUNT_API_FAIL)) {
            consistencyResponsor.doResponseWSError(response, "", 400, "Unknown error in request");
            return BizConsts.TYPE_ERROR_FLOW;
        }

        // 步骤7：记录消息到日志表
        // startTime = bizParam.getParamLong(BizConsts.KEY_RQUEST_START_TIME);
        LogUtil.saveLogToABM_TMall(request, bizResult.getCode(), startTime);

        // 步骤8：响应外部
        // doResponse 不允许向外抛异常
        consistencyResponsor.doResponse(bizResult, response);
        return BizConsts.TYPE_FINE_FLOW;

    }

}
